#include "include/defines.h"
#include "include/sockets/sockets.h"
#include "include/sdl/pantalla.h"
#include "include/s_func/tateti.h"

// |O| |X|
// |O|X|O| The TaTe-Ti Tournament - ServidorPartida
// |X| | |

// Estructura movimiento
s_mov mov;

// Estructura que almacena los sockets
s_sockets socks;

// Threads IDs
pthread_t tid_socket;
pthread_t tid_pantalla;
pthread_t tid_lectura;

// Semáforos threads
sem_t mutex_pantalla;
sem_t mutex_periferico;
sem_t mutex_socket;
sem_t mutex_socket_s;
sem_t socket_s_disp;

// Semáforos movimientos
sem_t nuevo_mov;
sem_t sem_mov;
sem_t mov_valido;

int main (int argc, char **argv)
{
	int victoriasJ1, victoriasJ2, ganador;
	int turno, fichas[2], tablero[TABLERO][TABLERO];
	int fOrigen, cOrigen, fDestino, cDestino, pos;		// [0]=Servidor | [1]=Jugador1 | [2]=Jugador2
	short int ult_mov = 0;								// Registra último mov
	int value=-1;
	
	// Semáforo
	sem_init(&sem_mov,4,1);							// Mutex para mov
	sem_init(&nuevo_mov,4,0);						// Mutex para mov
	
	// Semáforos sincronización threads
	sem_init(&mutex_socket_s,3,0);
	sem_init(&socket_s_disp,3,1);
	
	// Inicio Thread Socket
	pthread_create(&tid_socket, NULL, thread_socket_s, (void*) &mov);	
	
	sleep(1);
	
	while(1) // ServidorPartida ciclará hasta que deba morir.. (R.I.P. q' descance en paz)
	{
		turno = -1;
		victoriasJ1 = victoriasJ2 = 0;
		
		//ObtenerClientes();						// Papá me dice quienes serán los jugadores
		sem_wait(&nuevo_mov);

		while(victoriasJ1 != 2 && victoriasJ2 != 2) // Condición de fin de la partida
		{
			fichas[0] = fichas[1] = 0;
			InicializarTablero(tablero);

			do
			{
				SeleccionaTurno(&turno);								

				if(fichas[turno-1] < 3)				// Proceso una colocación de ficha
				{
					do
					{
						// Modifico movimiento
						sem_wait(&sem_mov);
						mov.estado = 0;					// No hay ganador todavía
						mov.accion = -1;				// Si tiene que repetir, por inválida
						mov.posicion = ult_mov;
						//sem_post(&sem_mov);
						
						printf("Espero movimiento cliente %d\n",turno);
						
						// Pido a thread_socket un envío
						unlock_socket_s(SEND,turno);
						
						// Espero resultado
						sem_wait(&nuevo_mov);
						sem_wait(&sem_mov);
						printf("Llego movimiento cliente %d : %d\n",turno,mov.posicion);			
						
						BuscarCoordenadas(tablero, mov.posicion, &fDestino, &cDestino);
						printf("BuscarCoordenadas OK, fd: %d | cd: %d\n",fDestino, cDestino);
					}while(!ColocarFicha(tablero, turno, fDestino, cDestino));
					
					// Confirmo movimiento
					printf("Tengo que confirmar movimiento\n");
					
					//sem_wait(&sem_mov);
					mov.accion = 1;
					//sem_post(&sem_mov);
					unlock_socket_s(CONF,turno);

					sem_wait(&sem_mov);
					ult_mov = mov.posicion;
					sem_post(&sem_mov);
					++fichas[turno-1];

					ImprimirTablero(tablero);
					sleep(1);
				}
				
				else  												// Proceso desplazamiento de ficha
				{
					printf("A mover ficha...\n");
					
					do
					{
						do
						{
							// Modifico movimiento
							sem_wait(&sem_mov);
							mov.estado = 0;					// No hay ganador todavía
							mov.accion = 0;					// Realizar movimiento de piezas
							//mov.posicion = ult_mov;
							//sem_post(&sem_mov);
							
							// Pido a thread_socket un envío
							unlock_socket_s(SEND,turno);
						
							// Espero resultado
							sem_wait(&nuevo_mov);
							sem_wait(&sem_mov);
							printf("Llego movimiento cliente %d : %d\n",turno,mov.posicion);

							BuscarCoordenadas(tablero, mov.posicion, &fOrigen, &cOrigen);
						}while(!EjecutarSeleccion(tablero, turno, fOrigen, cOrigen));
						
						//ult_mov = mov.posicion;
						
						//send() y recv() a jugador turno
						printf("\n\tFicha %c EjecutarJugada\n", turno == FICHA_O? 'O' : 'X');
						
						// Pido a thread_socket un envío
						unlock_socket_s(SEND,turno);
						
						// Espero resultado
						sem_wait(&nuevo_mov);
						sem_wait(&sem_mov);
						printf("\t%d -> %d\n",mov.posicion,mov.n_posicion);// scanf("%d", &pos);
						//BuscarCoordenadas(tablero, pos, &fOrigen, &cOrigen);
						BuscarCoordenadas(tablero, mov.n_posicion, &fDestino, &cDestino);
					}while(!EjecutarJugada(tablero, turno, fOrigen, cOrigen, fDestino, cDestino));
					
					// Guardo movimiento para enviarlo al otro cliente
					//mov.n_posicion = mov.posicion;
					
					tablero[fOrigen][cOrigen] = SIN_FICHA;
					tablero[fDestino][cDestino] = turno;
					
					ImprimirTablero(tablero);
					
					//Confirmo movimiento
					//sem_wait(&sem_mov);
					mov.accion = 2;
					printf("Movimiento de %d a %d de jugador %d\n",mov.posicion,mov.n_posicion,turno);
					//sem_post(&sem_mov);
					unlock_socket_s(CONF,turno);
				}

				ganador = HayGanador(tablero, turno);

			}while(ganador != FICHA_O && ganador != FICHA_X);

			// Confirmo ganador
			sem_wait(&sem_mov);
			mov.estado = 1;
			mov.accion = -1;
			mov.n_posicion = mov.posicion = 0;
			
			if(ganador == FICHA_O)
			{
				++victoriasJ1;
				unlock_socket_s(CONF,FICHA_O);
				
				// Confirmo perdedor
				sem_wait(&sem_mov);
				mov.estado = -1;
				unlock_socket_s(CONF,FICHA_X);
			}
			else
			{
				++victoriasJ2;
				unlock_socket_s(CONF,FICHA_X);
				
				// Confirmo perdedor
				sem_wait(&sem_mov);
				mov.estado = -1;
				unlock_socket_s(CONF,FICHA_O);
			}		
			
			ImprimirTablero(tablero);
			printf("\n\tGame Over - Ficha ganadora %c", ganador == FICHA_O? 'O' : 'X');

			printf("\n\tProxima partida en 2 segundos");
			sleep(2);
		}
		
		// send ganador y perdedor
		return 1;
	}
	
	return 0;
}
